using System;

namespace OracleInternal.Secure.Network
{
	internal class RC4 : EncryptionAlgorithm
	{
		internal new class RC4_a
		{
			private const ushort m_a = 256;

			private byte[] m_b = new byte[256];

			private int field_c;

			private int field_d;

			internal RC4_a()
			{
			}

			public void a(byte[] A_0, int A_1)
			{
				for (int i = 0; i < 256; i++)
				{
					this.m_b[i] = (byte)i;
				}
				field_c = (field_d = 0);
				int num = 0;
				int num2 = 0;
				int num3 = 0;
				while (num < 256)
				{
					byte b = this.m_b[num];
					if (num3 == A_1)
					{
						num3 = 0;
					}
					num2 = (num2 + b + A_0[num3]) & 0xFF;
					this.m_b[num] = this.m_b[num2];
					this.m_b[num2] = b;
					num++;
					num3++;
				}
			}

			public byte[] b(byte[] A_0, int A_1)
			{
				byte[] array = new byte[A_1];
				a(array, A_0, A_1);
				return array;
			}

			public void a(byte[] A_0, byte[] A_1, int A_2)
			{
				int num = field_c;
				int num2 = field_d;
				for (int i = 0; i < A_2; i++)
				{
					num = (num + 1) & 0xFF;
					int num3 = this.m_b[num];
					num2 = (num2 + num3) & 0xFF;
					int num4 = this.m_b[num2];
					this.m_b[num] = (byte)((uint)num4 & 0xFFu);
					this.m_b[num2] = (byte)((uint)num3 & 0xFFu);
					int num5 = (num3 + num4) & 0xFF;
					A_0[i] = (byte)((uint)(A_1[i] ^ this.m_b[num5]) & 0xFFu);
				}
				field_c = num;
				field_d = num2;
			}
		}

		private new const byte m_a = 123;

		private const byte b = byte.MaxValue;

		private const int c = 170;

		private const int d = 85;

		private const int e = 180;

		private const int f = 90;

		private RC4_a g;

		private RC4_a h;

		private RC4_a i;

		private bool j = true;

		private bool k;

		private int l = 40;

		public RC4()
		{
		}

		public RC4(bool A_0, int A_1)
		{
			switch (A_1)
			{
			case 40:
			case 56:
			case 128:
			case 256:
				l = A_1;
				j = A_0;
				break;
			default:
				throw new Exception("RC4: Invalid key size");
			}
		}

		public RC4(int A_0, byte[] A_1, byte[] A_2)
		{
			switch (A_0)
			{
			case 40:
			case 56:
			case 128:
			case 256:
				l = A_0;
				init(A_1, A_2);
				break;
			default:
				throw new Exception("RC4: Invalid key size");
			}
		}

		public RC4(int A_0, byte[] A_1, byte[] A_2, bool A_3)
		{
			l = A_0;
			k = true;
			j = false;
			init(A_1, A_2);
		}

		public override void init(byte[] key, byte[] iv)
		{
			g = new RC4_a();
			h = new RC4_a();
			i = new RC4_a();
			setSessionKey(key, iv);
		}

		public override byte[] decrypt(byte[] ciphertext)
		{
			if (j)
			{
				byte[] sourceArray = i.b(ciphertext, ciphertext.Length - 1);
				byte[] array = new byte[ciphertext.Length - 1];
				Array.Copy(sourceArray, 0, array, 0, ciphertext.Length - 1);
				return array;
			}
			return i.b(ciphertext, ciphertext.Length);
		}

		public override byte[] decrypt(byte[] buffer, int length)
		{
			if (length > buffer.Length)
			{
				throw new Exception("RC4: Invalid buffer length");
			}
			if (j)
			{
				byte[] sourceArray = i.b(buffer, length - 1);
				byte[] array = new byte[length - 1];
				Array.Copy(sourceArray, 0, array, 0, length - 1);
				return array;
			}
			return i.b(buffer, length);
		}

		public override byte[] encrypt(byte[] buffer, int length)
		{
			if (length > buffer.Length)
			{
				throw new Exception("RC4: Invalid buffer length");
			}
			byte[] array = h.b(buffer, length);
			if (j)
			{
				byte[] array2 = new byte[length + 1];
				Array.Copy(array, 0, array2, 0, length);
				array2[length] = 0;
				return array2;
			}
			return array;
		}

		public override byte[] encrypt(byte[] plaintext)
		{
			byte[] array = h.b(plaintext, plaintext.Length);
			if (j)
			{
				byte[] array2 = new byte[plaintext.Length + 1];
				Array.Copy(array, 0, array2, 0, plaintext.Length);
				array2[plaintext.Length] = 0;
				return array2;
			}
			return array;
		}

		public override int maxDelta()
		{
			return 1;
		}

		public override void setSessionKey(byte[] key, byte[] iv)
		{
			if (key == null && iv == null)
			{
				a();
				return;
			}
			int num = l / 8;
			if (key.Length < num)
			{
				throw new Exception("RC4: Invalid key length");
			}
			int num2 = 0;
			if (iv != null)
			{
				num2 = iv.Length;
			}
			byte[] array = new byte[num + 1 + num2];
			Array.Copy(key, key.Length - num, array, 0, num);
			if (!k)
			{
				array[num] = 123;
			}
			else
			{
				array[num] = byte.MaxValue;
			}
			if (iv != null)
			{
				Array.Copy(iv, 0, array, num + 1, iv.Length);
			}
			g.a(array, array.Length);
			a();
		}

		internal new void a()
		{
			byte[] array = new byte[36]
			{
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32,
				32
			};
			int num = l / 8;
			if (!k)
			{
				byte[] array2 = g.b(array, num);
				if (j)
				{
					array2[num - 1] ^= 170;
				}
				i.a(array2, num);
				array2[num - 1] ^= 170;
				h.a(array2, num);
			}
			else
			{
				byte[] array3 = new byte[num + 1];
				g.a(array3, array, num);
				array3[num] = 180;
				i.a(array3, num + 1);
				array3[num] = 90;
				h.a(array3, num + 1);
			}
		}
	}
}
